#include <graphics.h>
#include <Windows.h>
#include <iostream>
using namespace std;
#define MAPX 32//virtual coord
#define MAPY 32//virtual coord
#define MAXLENGTH 1023
#define U 11
//function defination
void mainInit();
void dataSych();
void render();
void dotGraph(int _x, int _y, bool behavior);
char keyControl();
void changeCoordByDirect();
bool gameJudge();
void snakeDataInherit();
//----------class defination
class Block {
public:
	Block() :blockX(0), blockY(0) {
		graphState = false;
	}
	void operator=(Block& _block) {
		this->blockX = _block.blockX;
		this->blockY = _block.blockY;
		this->graphState = _block.graphState;
	}
	int blockX;//drawing coord
	int blockY;//drawing coord
	bool graphState;
};
//----------value defination
Block blocks[MAPX][MAPY];
Block snake[MAXLENGTH];//snake[0]==head
ExMessage keyMes;
int length = 15;
char direct = 'W';
void debug() {
	cout << "snake0:" << snake[0].blockX / U << " " << snake[0].blockY / U
		<< " " << snake[0].graphState << " "
		<< "snake1:" << snake[1].blockX / U << " " << snake[1].blockY / U
		<< " " << snake[1].graphState << " "
		<< direct << "  "
		<< keyControl() << "  "
		<< length << endl;
}
//----------main function------------------------------------------------------------------------------------
int main() {
	mainInit();
	snake[1].blockX = snake[0].blockX;
	snake[1].blockY = snake[0].blockY - U;
	dataSych();
	int temp = 0;
	while (true) {
		peekmessage(&keyMes, EX_KEY, true);
		debug();
		Sleep(8);
		if (temp % 25 == 0) {
			changeCoordByDirect();
			dataSych();
			render();
		}
		if (gameJudge() == true) break;
		temp++;
	}
	return 0;
}
//---------function makeup
void blocksInit();
void headInit();
void mainInit() {
	blocksInit();
	headInit();
	initgraph(MAPX * U, MAPY * U, EX_NOCLOSE | EX_SHOWCONSOLE);
}
void blocksInit() {
	for (int i = 0; i < MAPX; i++) {
		for (int j = 0; j < MAPY; j++) {
			blocks[i][j].blockX = U * i;
			blocks[i][j].blockY = U * j;
			blocks[i][j].graphState = false;
		}
	}
}
void headInit() {
	snake[0].blockX = 15 * U;
	snake[0].blockY = 15 * U;
	snake[0].graphState = true;//unuseful

}
void dataSych() {//sychrnize the data of Blocks[][] and Snake[]
	for (int x = 0; x < MAPX; x++) {
		for (int y = 0; y < MAPY; y++) {
			blocks[x][y].graphState = false;
		}
	}
	int tempX, tempY;
	for (int i = 0; i <= length ; i++) {
		tempX = snake[i].blockX / U;
		tempY = snake[i].blockY / U;
		blocks[tempX][tempY].graphState = true;
	}
}
void render() {
	for (int x = 0; x < MAPX; x++) {
		for (int y = 0; y < MAPY; y++) {
			if (blocks[x][y].graphState == true)
				dotGraph(x, y, true);
			else if (blocks[x][y].graphState == false)
				dotGraph(x, y, false);
		}
	}
}
void dotGraph(int _x, int _y, bool behavior) {
	if (behavior == true)
		fillrectangle(blocks[_x][_y].blockX, blocks[_x][_y].blockY,
			blocks[_x][_y].blockX + 11, blocks[_x][_y].blockY + 11);
	else if (behavior == false)
		clearrectangle(blocks[_x][_y].blockX, blocks[_x][_y].blockY,
			blocks[_x][_y].blockX + 11, blocks[_x][_y].blockY + 11);
}
char keyControl() {
	if (keyMes.message == WM_KEYUP) {
		if (keyMes.vkcode == 'W' && direct != 'S') {
			direct = keyMes.vkcode;
			keyMes.vkcode = ' ';
			return 'W';
		}
		else if (keyMes.vkcode == 'S' && direct != 'W') {
			direct = keyMes.vkcode;
			keyMes.vkcode = ' ';
			return 'S';
		}
		else if (keyMes.vkcode == 'A' && direct != 'D') {
			direct = keyMes.vkcode;
			keyMes.vkcode = ' ';
			return 'A';
		}
		else if (keyMes.vkcode == 'D' && direct != 'A') {
			direct = keyMes.vkcode;
			keyMes.vkcode = ' ';
			return 'D';
		}
		else return 'N';
	}
	else return 'n';
}
void changeCoordByDirect() {
	if (direct == 'W') {
		snakeDataInherit();
		snake[0].blockY = snake[0].blockY - U;
	}
	else if (direct == 'S') {
		snakeDataInherit();
		snake[0].blockY = snake[0].blockY + U;
	}
	else if (direct == 'A') {
		snakeDataInherit();
		snake[0].blockX = snake[0].blockX - U;
	}
	else if (direct == 'D') {
		snakeDataInherit();
		snake[0].blockX = snake[0].blockX + U;
	}
}
void snakeDataInherit() {
	for (int i = length; i > 0; i--) {
		snake[i] = snake[i - 1];
	}
}
bool gameJudge() {
	if (snake[0].blockX / U >= MAPX || snake[0].blockY / U >= MAPY ||
		snake[0].blockX / U < 0 || snake[0].blockY / U < 0) return true;
	else return false;
}

